#include <wx/wx.h>
#include <wx/config.h>
#include <wx/fileconf.h>
#include <wx/wfstream.h>
#include "settings.h"
#include "util.h"

#if defined(TARGET_WIN32)
  #define WIN32_LEAN_AND_MEAN
  #include <windows.h>
#endif

Config* config;

#ifdef TARGET_WIN32
// undocumented
extern wxFont wxCreateFontFromLogFont(const LOGFONT *logFont);
#endif

void Config::ResetDefaults()
{
    // get system font
#ifdef TARGET_WIN32         // on Windows, get the default MessageBox font
    wxFont system_font;
    NONCLIENTMETRICS ncm;
    ncm.cbSize = sizeof(ncm) - sizeof(ncm.iPaddedBorderWidth);  //seriously, fuck MS ungently with this iPaddedBorderWidth
    if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0))
        system_font = wxCreateFontFromLogFont(&ncm.lfMessageFont);
    else {
        dbg("SystemParametersInfo() failed, errcode=%d\n", GetLastError());
        system_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
    }
#else
    wxFont system_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
#endif

    wxFont default_font;
    default_font.SetPointSize(14);

    wxFont bold_font = default_font;
    bold_font.SetWeight(wxBOLD);

    wxFont italic_font = default_font;
    italic_font.SetStyle(wxITALIC);

    wxFont underlined_font = default_font;
    underlined_font.SetUnderlined(true);

    wxFont underlinedbold_font = default_font;
    underlinedbold_font.SetWeight(wxBOLD);
    underlinedbold_font.SetUnderlined(true);

    for (int x=0; x<FONT_MAX; x++) {
        fonts[x].attr.SetFont(default_font);
    }
    fonts[FONT_DEFAULT].name      = "default";
    fonts[FONT_CAPTION].name      = "caption";
    fonts[FONT_DATE].name         = "date";
    fonts[FONT_ERROR].name        = "error";
    fonts[FONT_KEYWORD].name      = "keyword";
    fonts[FONT_KEYWORD_MARK].name = "keyword_mark";
    fonts[FONT_UNK_KEYWORD].name  = "unknown_keyword";
    fonts[FONT_SOURCE].name       = "source";

    fonts[FONT_CAPTION].attr.SetFont(underlinedbold_font);
    fonts[FONT_SOURCE].attr.SetFont(italic_font);
    fonts[FONT_DATE].attr.SetFont(bold_font);
    fonts[FONT_ERROR].attr.SetFont(bold_font);
    fonts[FONT_ERROR].attr.SetTextColour(*wxRED);
    fonts[FONT_KEYWORD].attr.SetFont(underlined_font);
    fonts[FONT_UNK_KEYWORD].attr.SetFont(underlined_font);
    fonts[FONT_UNK_KEYWORD].attr.SetTextColour(wxColor(100,0,0));
    fonts[FONT_SOURCE].attr.SetFont(italic_font);
    fonts[FONT_SOURCE].attr.SetTextColour(wxColour(100,100,200));

//    for (int x=0; x<FONT_MAX; x++) {
//        fonts[x].attr.SetFlags(wxTEXT_ATTR_FONT | wxTEXT_ATTR_TEXT_COLOUR);
//    }

    scroll_speed = 10;
}

Config::Config(const wxString& config_file_name)
{
    this->config_file_name = config_file_name;

    ResetDefaults();
}

void Config::LoadLang()
{
    wxFileInputStream f(config_file_name);
    if (!f.IsOk()) {
        lang = "";
        return;
    }
    wxFileConfig file_config(f);
    if (!file_config.Read("lang", &lang) || lang=="") {
        int system_lang_id = wxLocale::GetSystemLanguage();
        if (system_lang_id == wxLANGUAGE_UNKNOWN) {
            dbg("wxLocale::GetSystemLanguage() failed");
            return;
        }
        const wxLanguageInfo *langinfo = wxLocale::GetLanguageInfo(system_lang_id);
        if (langinfo == 0) {
            dbg("wxLocale::GetLanguageInfo() failed for langid %d", system_lang_id);
            return;
        }
        lang = langinfo->CanonicalName;
    }
}

bool Config::Load()
{
    wxFileInputStream f(config_file_name);
    if (!f.IsOk())
        return false;
    wxFileConfig file_config(f);

    // general
    file_config.Read("scroll_speed", &scroll_speed);

    // fonts
    for (int i=0; i<FONT_MAX; i++) {
        wxString font_name = fonts[i].name + "_font";
        wxString font_desc;
        wxFont f;
        if (file_config.Read(font_name, &font_desc)) {
            if (!f.SetNativeFontInfoUserDesc(font_desc))
                ErrMsg(_("Invalid font description '%s' in config file"), font_desc);
            fonts[i].attr.SetFont(f);
        }
    }

    return true;
}

void Config::Save()
{
    wxFileOutputStream f(config_file_name);
    wxFileConfig file_config;

    bool ok=true;

    // general
    ok &= file_config.Write("lang", lang);
    ok &= file_config.Write("scroll_speed",  scroll_speed);

    // fonts
    // (GetNativeFontInfoUserDesc seems to ignore 'underlined' property, no idea why)
    for (int i=0; i<FONT_MAX; i++) {
        wxString font_name = fonts[i].name + "_font";
        wxString font_desc = fonts[i].attr.GetFont().GetNativeFontInfoUserDesc();
        ok &= file_config.Write(font_name, font_desc);
    }

    if (ok) {
        ok &= file_config.Save(f, wxConvUTF8);
        f.Close();
    }
    if (!ok)
        ErrMsg("Failed to save settings");
}

bool Config::GetLangDesc(const wxString& lang, wxLanguageInfo *langinfo) const
{
    if (lang.IsEmpty())
        return false;
    const wxLanguageInfo *planginfo = wxLocale::FindLanguageInfo(lang);
    if (!planginfo)
        return false;
    *langinfo = *planginfo;
    return true;
}

bool Config::CheckLangString(const wxString& lang) const
{
    wxLanguageInfo dummy;
    return GetLangDesc(lang, &dummy);
}
